package edu.cmu.ibill.controller;

import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import edu.cmu.ibill.databeans.*;
import edu.cmu.ibill.model.*;

import org.jfree.chart.*;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.time.Month;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;

import java.util.Date;

public class ShowReportAction extends Action {

	PersonalBillDAO personalbillDAO;
	UserDAO userDAO;
	CategoryDictDAO categorydictDAO;
	DebtDAO debtDAO;
	
	String prefix = "../webapps/webapp/";

	public ShowReportAction(Model model) {
		this.personalbillDAO = model.getPersonalBillDAO();
		this.userDAO = model.getUserDAO();
		this.categorydictDAO = model.getCategoryDictDAO();
		this.debtDAO = model.getDebtDAO();
	}

	@Override
	public String getName() {
		return "report.do";
	}

	@Override
	public String perform(HttpServletRequest request) {

		List<String> errors = new ArrayList<String>();
		request.setAttribute("addpersonalbillerrors", errors);
		User user = (User) request.getSession(false).getAttribute("user");

		String categorychartpath = getCategoryPieChart(user, errors);
		request.setAttribute("categorychartpath", categorychartpath);

		String collectchartpath = getUserCollectPieChart(user, errors);
		request.setAttribute("collectchartpath", collectchartpath);

		String returnchartpath = getUserReturnPieChart(user, errors);
		request.setAttribute("returnchartpath", returnchartpath);

		String monthlysummarypath = getMonthlySummaryChart(user, errors,
				request);
		request.setAttribute("monthlysummarypath", monthlysummarypath);

		return "statistics.jsp";
	}

	public String getCategoryPieChart(User user, List<String> errors) {
		int userId = user.getId();

		HashMap<Integer, Double> categoricalSummary = new HashMap<Integer, Double>();

		PersonalBill[] bills = personalbillDAO.LookupByUserId(userId);

		for (PersonalBill bill : bills) {
			int catId = bill.getCategoryId();
			if (categoricalSummary.containsKey(catId))
				categoricalSummary.put(catId, categoricalSummary.get(catId)
						+ Math.abs(bill.getAmount()));
			else
				categoricalSummary.put(catId, Math.abs(bill.getAmount()));
		}

		DefaultPieDataset piedata = new DefaultPieDataset();

		for (int id : categoricalSummary.keySet()) {
			String name = categorydictDAO.LookupCategoryName(id);
			double value = categoricalSummary.get(id);
			if (name == null || name.equals("income") || value == 0)
				continue;
			else {
				piedata.setValue(name, value);
			}
		}

		JFreeChart chart = ChartFactory.createPieChart("Categorical Analysis",
				piedata, true, true, false);
		chart.setBackgroundPaint(Color.white);
		
		PiePlot plot = (PiePlot) chart.getPlot();

		plot.setBackgroundPaint(Color.white);
		
		plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}: {2}",
				NumberFormat.getNumberInstance(), new DecimalFormat("0.00%")));

		int[] color = { 0x00, 0x00, 0x10 };
		int index = 2;

		for (int i = 0; i < categoricalSummary.size(); i++) {
			if (color[index] + 30 > 0xFF)
				index++;
			index = index % 3;
			color[index] += 30;
			plot.setSectionPaint(i, new Color(color[0], color[1], color[2]));
		}

		String filename = "charts/category_user" + user.getId() + ".png";

		try {
			File file = new File(prefix+filename);
			if(file.exists())
				file.delete();
			ChartUtilities.saveChartAsPNG(file, chart, 300, 300);
			return filename;
		} catch (IOException e) {
			errors.add(e.getMessage());
		}

		return "fail";
	}

	public String getUserCollectPieChart(User user, List<String> errors) {
		int userId = user.getId();

		Debt[] needCollectDebts = debtDAO.LookupByPayedId(userId);

		HashMap<Integer, Double> summary = new HashMap<Integer, Double>();

		for (Debt debt : needCollectDebts) {
			int owedUserid = debt.getOwedId();
			if (summary.containsKey(owedUserid))
				summary.put(owedUserid,
						summary.get(owedUserid) + debt.getAmount());
			else
				summary.put(owedUserid, debt.getAmount());
		}

		DefaultPieDataset piedata = new DefaultPieDataset();

		for (int id : summary.keySet()) {
			piedata.setValue(userDAO.getNamebyUserID(id),
					Math.abs(summary.get(id)));
		}

		JFreeChart chart = ChartFactory.createPieChart("You need to collect",
				piedata, true, true, false);
		chart.setBackgroundPaint(Color.white);

		PiePlot plot = (PiePlot) chart.getPlot();
		
		plot.setBackgroundPaint(Color.white);

		plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}: {2}",
				NumberFormat.getNumberInstance(), new DecimalFormat("0.00%")));

		int[] color = { 0x00, 0x00, 0x00 };
		int index = 0;

		for (int i = 0; i < summary.size(); i++) {
			if (color[index] + 30 > 0xFF)
				index++;
			index = index % 3;
			color[index] += 30;
			plot.setSectionPaint(i, new Color(color[0], color[1], color[2]));
		}

		String filename = "charts/collect_user" + user.getId() + ".png";

		try {
			File file = new File(prefix+filename);
			if(file.exists())
				file.delete();
			ChartUtilities.saveChartAsPNG(file, chart, 300, 300);
			return filename;
		} catch (IOException e) {
			errors.add(e.getMessage());
		}

		return "fail";
	}

	public String getUserReturnPieChart(User user, List<String> errors) {
		int userId = user.getId();

		Debt[] needReturnDebts = debtDAO.LookupByOwedId(userId);

		HashMap<Integer, Double> summary = new HashMap<Integer, Double>();

		for (Debt debt : needReturnDebts) {
			int owedUserid = debt.getOwedId();
			if (summary.containsKey(owedUserid))
				summary.put(owedUserid,
						summary.get(owedUserid) + debt.getAmount());
			else
				summary.put(owedUserid, debt.getAmount());
		}

		DefaultPieDataset piedata = new DefaultPieDataset();

		for (int id : summary.keySet()) {
			piedata.setValue(userDAO.getNamebyUserID(id),
					Math.abs(summary.get(id)));
		}

		JFreeChart chart = ChartFactory.createPieChart("You need to return",
				piedata, true, true, false);
		chart.setBackgroundPaint(Color.white);

		PiePlot plot = (PiePlot) chart.getPlot();
		
		plot.setBackgroundPaint(Color.white);

		plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}: {2}",
				NumberFormat.getNumberInstance(), new DecimalFormat("0.00%")));

		int[] color = { 0x00, 0x00, 0x00 };
		int index = 0;
		for (int i = 0; i < summary.size(); i++) {
			if (color[index] + 30 > 0xFF)
				index++;
			index = index % 3;
			color[index] += 30;
			plot.setSectionPaint(i, new Color(color[0], color[1], color[2]));
		}

		String filename = "charts/return_user" + user.getId() + ".png";

		try {
			File file  = new File(prefix+filename);
			if(file.exists())
				file.delete();
			ChartUtilities.saveChartAsPNG(file, chart, 300, 300);
			return filename;
		} catch (IOException e) {
			errors.add(e.getMessage());
		}

		return "fail";
	}

	public String getMonthlySummaryChart(User user, List<String> errors,
			HttpServletRequest request) {

		Date date = new Date();
		int year = date.getYear();

		TimeSeries timeseries = new TimeSeries("Monthly Income",
				org.jfree.data.time.Month.class);

		TimeSeries timeseries1 = new TimeSeries("Monthly Expense",
				org.jfree.data.time.Month.class);

		for (int i = 1; i <= 12; i++) {
			timeseries.add(new Month(i, year + 1900),
					personalbillDAO.getMonthIncome(year, i, user.getId()));
			timeseries1.add(new Month(i, year + 1900),
					personalbillDAO.getMonthExpense(year, i, user.getId()));
		}

		TimeSeriesCollection timeseriescollection = new TimeSeriesCollection();
		timeseriescollection.addSeries(timeseries);
		timeseriescollection.addSeries(timeseries1);

		JFreeChart chart = ChartFactory.createTimeSeriesChart(
				"Monthly Income & Expense Summary", "Date", "Income",
				timeseriescollection, true, true, false);

		XYPlot xyplot = (XYPlot) chart.getPlot();

		xyplot.setBackgroundPaint(Color.white);
		xyplot.setDomainGridlinePaint(Color.LIGHT_GRAY);
		xyplot.setRangeGridlinePaint(Color.LIGHT_GRAY);

		xyplot.setDomainCrosshairVisible(true);
		xyplot.setRangeCrosshairVisible(true);

		String filename = "charts/monthlyincome_user"
				+ user.getId() + ".png";

		String error;

		try {
			File file = new File(prefix+filename);
			if(file.exists())
				file.delete();
			ChartUtilities.saveChartAsPNG(file, chart, 900, 300);
			return filename;
		} catch (IOException e) {
			errors.add(e.getMessage());
			error = e.getMessage();
			e.printStackTrace();
		}

		return "failedToSave " + error;
	}

}
